/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.kreig133.xml;

import com.kreig133.builder.ParametrsForBuild;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author eshangareev
 */
public class XmlParser {

    final static public String ANALYTIC = "//Handler/*";
    final static public String MODEL = "/spine_model/*/*";
    final static public String EXPERIMENT = "/*/*";
    private String current;
    protected DocumentBuilderFactory factory;
    protected DocumentBuilder builder;
    protected Document doc;
    protected Element root;
    protected XPathFactory xpfactory = XPathFactory.newInstance();
    protected XPath path;

    protected XmlParser() throws ParserConfigurationException {
        factory = DocumentBuilderFactory.newInstance();
        factory.setIgnoringElementContentWhitespace(true);
        builder = factory.newDocumentBuilder();
        path = xpfactory.newXPath();
    }

    public boolean parseXML(final File xmlFile) {
        try {
            doc = builder.parse(xmlFile);
            root = doc.getDocumentElement();
            return true;
        } catch (SAXException ex) {
            System.err.println("XML is not valid");
            return false;
        } catch (IOException ex) {
            System.err.println("Error. IOException.");
            return false;
        }
    }

    public ParametrsForBuild getParametrsForBuild() {
        try {

            if (root != null) {
                ParametrsForBuild result = new ParametrsForBuild();

                NodeList nodes = (NodeList) path.evaluate(current,
                        root, XPathConstants.NODESET);
                for (int i = 0; i < nodes.getLength(); i++) {
                    Map<String, String> temp = parseNextElement(nodes.item(i));
                    if (temp == null ? false : temp.size() > 0) {
                        result.addParametrs(temp);
                    }
                }
                return result;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public Map<String, String> parseNextElement(Node next)
            throws XPathExpressionException {
        Map<String, String> result = new HashMap<String, String>();
        //Заносим название класса.
        result.put("class", next.getNodeName());

        // Настраиваем разбор для потомков 
        if (current == XmlParser.MODEL) {
            Node node = (Node) path.evaluate("./algorithm/*", next, XPathConstants.NODE);
            if (node != null) {
                result.put("algorithm", node.getNodeName());
            }
        }

        //Заносим аттрибуты.
        NodeList nodes = (NodeList) path.evaluate("./@*", next, XPathConstants.NODESET);

        for (int i = 0; i < nodes.getLength(); i++) {
            result.put(nodes.item(i).getNodeName(), nodes.item(i).getNodeValue());
        }

        return result.isEmpty() ? null : result;
    }

    static public XmlParser createXmlParser(String type) {
        try {
            XmlParser result = new XmlParser();
            result.setCurrent(type);
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    private void setCurrent(String current) {
        this.current = current;
    }
}
